package research.ui.editors;

import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IEditorSite;
import org.eclipse.ui.IWorkbenchPartConstants;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.part.EditorPart;

import research.entity.Entity;
import research.persistence.IPersistenceManager;
import research.persistence.PersistenceManager;
import research.ui.editors.input.EntityEditorInput;
import research.ui.editors.listeners.DateSelectionListener;
import research.ui.editors.listeners.EntityTableModifyListener;
import research.ui.editors.listeners.NameModifyListener;
import research.ui.editors.listeners.TextModifyListener;

public abstract class EntityEditor extends EditorPart {
	protected Entity entity;
	private boolean isDirty = false;
	
	private NameModifyListener nameModifyListener = new NameModifyListener(this);
	private TextModifyListener textModifyListener = new TextModifyListener(this);
	private DateSelectionListener dateSelectionListener = new DateSelectionListener(this);
	private EntityTableModifyListener entityTableListener = new EntityTableModifyListener(this);
	
	public EntityEditor() {
		super();
	}
	
	protected IPersistenceManager getPersistenceManager() {
		return PersistenceManager.getInstance(); 
	}
	
	protected boolean isNewEntity() {
		return !getPersistenceManager().getDataSource().isPersistent(entity);
	}

	@Override
	public void doSave(IProgressMonitor monitor) {
		if (readAndValidate()) {
			getPersistenceManager().persist(entity);
			persist();
			
			updateTitle();
			setDirty(false);
		}
	}

	@Override
	public void doSaveAs() {
	}

	@Override
	public void init(IEditorSite site, IEditorInput input)
			throws PartInitException {
		if (!(input instanceof EntityEditorInput) || !checkInputEntityType((EntityEditorInput) input))
			throw new PartInitException("Invalid Editor Input");
		
		setSite(site);
		setInput(input);
		
		entity = ((EntityEditorInput) input).getEntity();
		
		initialize();
	}

	@Override
	public boolean isDirty() {
		return this.isDirty;
	}

	@Override
	public boolean isSaveAsAllowed() {
		return false;
	}

	@Override
	public void createPartControl(Composite parent) {
		render(parent);
		
		fill();
		updateTitle();
		
		setDirty(isNewEntity());
	}

	private void updateTitle() {
		if (!isNewEntity())
			setPartName(entity.toString());
	}

	@Override
	public void setFocus() {
	}
	
	public void setDirty(boolean dirty) {
		this.isDirty = dirty;
		firePropertyChange(IWorkbenchPartConstants.PROP_DIRTY);
	}
	
	public void updateFormTitle(String title) {
		setFormTitle(title);
	}
	
	protected NameModifyListener getNameModifyListener() {
		return nameModifyListener;
	}

	protected TextModifyListener getTextModifyListener() {
		return textModifyListener;
	}
	
	public DateSelectionListener getDateSelectionListener() {
		return dateSelectionListener;
	}

	public EntityTableModifyListener getEntityTableListener() {
		return entityTableListener;
	}

	protected abstract boolean checkInputEntityType(EntityEditorInput input);
	
	protected abstract boolean readAndValidate();
	
	protected abstract void fill();
	
	protected abstract void setFormTitle(String title);
	
	protected abstract void initialize();
	
	protected abstract void render(Composite parent);

	protected void persist() {
	}

}
